package cn.edu.xmu.javaee.productdemojpa.dao;

import cn.edu.xmu.javaee.core.bean.RequestVariables;
import cn.edu.xmu.javaee.core.exception.BusinessException;
import cn.edu.xmu.javaee.core.model.ReturnNo;
import cn.edu.xmu.javaee.core.util.JacksonUtil;
import cn.edu.xmu.javaee.productdemojpa.dao.bo.Product;
import cn.edu.xmu.javaee.productdemojpa.mapper.join.JoinProductPoMapper;
import cn.edu.xmu.javaee.productdemojpa.mapper.join.po.JoinProductPo;
import cn.edu.xmu.javaee.productdemojpa.util.CloneFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.dao.DataAccessException;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static cn.edu.xmu.javaee.core.model.Constants.PLATFORM;

@Slf4j
@RequiredArgsConstructor
@Repository("jpa")
public class JpaProductDao implements FindProduct {

    private final MessageSource messageSource;
    private final RequestVariables requestVariables;
    private final JoinProductPoMapper joinProductPoMapper;

    @Override
    public Product findById(Long shopId, Long productId) throws BusinessException {
        Product product = null;
        Locale locale = requestVariables.getLocale();
        log.debug("findById: shopId = {}, productId = {}, locale = {}", shopId, productId, locale);
        JoinProductPo joinProductPo;
        try {
            Optional<JoinProductPo> ret = this.joinProductPoMapper.findById(productId);
            joinProductPo = ret.orElseThrow(()->
                    new BusinessException(ReturnNo.RESOURCE_ID_NOTEXIST, JacksonUtil.toJson(new String[] {messageSource.getMessage("product", null, locale), productId.toString()})));
            if (!Objects.equals(shopId, joinProductPo.getShopId()) && !PLATFORM.equals(shopId)) {
                String[] objects = new String[]{messageSource.getMessage("product", null, locale), productId.toString(), shopId.toString()};
                throw new BusinessException(ReturnNo.RESOURCE_ID_OUTSCOPE, JacksonUtil.toJson(objects));
            }

        } catch (DataAccessException e) {
            log.error("findById: error = {}", e);
            throw new BusinessException(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
        return CloneFactory.copy(new Product(), joinProductPo);
    }

    @Override
    public List<Product> retrieveByName(Long shopId, String name) throws BusinessException {
        List<Product> productList;
        try {
            List<JoinProductPo> productPoList;
            Pageable pageable = PageRequest.of(0, 100);
            if (PLATFORM.equals(shopId)) {
                productPoList = this.joinProductPoMapper.findByName(name, pageable);
            }else {
                productPoList = this.joinProductPoMapper.findByShopIdAndName(shopId, name, pageable);
            }
            log.debug("retrieveByName: productPoList = {}", productPoList);
            productList = productPoList.stream().map(o -> CloneFactory.copy(new Product(), o)).collect(Collectors.toList());
            log.debug("retrieveByName: productList = {}", productList);
        } catch (DataAccessException e) {
            log.error(e.getMessage());
            throw new BusinessException(ReturnNo.INTERNAL_SERVER_ERR, e.getMessage());
        }
        return productList;    }
}
